package br.com.vexillum.control;

import java.util.HashMap;
import java.util.Map;

import br.com.vexillum.control.manager.EmailManager;
import br.com.vexillum.control.manager.ExceptionManager;
import br.com.vexillum.control.persistence.GenericPersistence;
import br.com.vexillum.control.validator.Validator;
import br.com.vexillum.model.CommonEntity;
import br.com.vexillum.model.annotations.ValidatorClass;
import br.com.vexillum.util.ReflectionUtils;
import br.com.vexillum.util.Return;

@SuppressWarnings("unchecked")
public class GenericControl<E extends CommonEntity> implements IGenericControl<E> {
	
	private GenericPersistence<E> persistence;
	protected HashMap<String, Object> data;
	
	protected E entity;
	protected Class<E> classEntity;
	
	public GenericControl(HashMap<String, Object> data){
		persistence  = new GenericPersistence<E>();
		if(data == null){
			this.data = new HashMap<String, Object>();
			entity = null;
		} else {
			this.data = data;
			entity = (E) data.get("entity");
		}
		classEntity = ReflectionUtils.getGenericType(this);
	}
	
	
	public HashMap<String, Object> getData() {
		return data;
	}

	public void setData(HashMap<String, Object> data) {
		this.data = data;
	}
	

	public Return doAction(String action) {
		Return ret = new Return(true);
		Class<?> rclass = this.getClass();
		try {
			data.put("action", action);
//			Method m = rclass.getMethod(action, new Class[]{});
			ret.concat(validateEntity(action));
			if(ret.isValid()){
				ret.concat((Return) (rclass.getMethod(action, new Class[]{})).invoke(this, new Object[]{}));
			}
		} catch (Exception e) {
			ret.concat(new ExceptionManager(e).treatException());
		} 
		return ret;
	}		
	
	@SuppressWarnings("rawtypes")
	private Return validateEntity(String action) {
		Return ret = new Return(true);
		if(entity != null){
			try {
				Class validatorClass = getValidatorClass();
				Validator validator = (Validator) validatorClass.getConstructor(new Class[]{Map.class}).newInstance(data);
				ret.concat(validator.validate());
			} catch (Exception e) {
				ret = new ExceptionManager(e).treatException();
			}
		}
		return ret;
	}


	@SuppressWarnings("rawtypes")
	private Class getValidatorClass() throws ClassNotFoundException{
		ValidatorClass an = entity.getClass().getAnnotation(ValidatorClass.class);
		if(entity != null && an != null){
			return Class.forName(an.validatorClass());
		}
		return Validator.class;
	}
	
	public Return save(){
		 return persistence.save(entity);
	}
	
	public Return delete(){
		return persistence.delete(entity);
	}

	public Return update(){
		return persistence.update(entity);
	}

	public Return searchByCriteria(){
		return persistence.searchByCriteria(entity);
	}
	
	public Return searchByHQL(){
		return persistence.searchByHQL((String) data.get("sql"));
	}
	
	//TODO Arrumar uma forma de detectar se é a pesquisa por entidade ou pela hql
	/*public Return searchByHQL(){
		return persistence.searchByHQL((String) data.get("hql"));
	}*/
	
	public Return searchByNativeSQL(){
		return persistence.searchByNativeSQL((String) data.get("sql"));
	}

	public Return listAll(){
		return persistence.listAll((Class<CommonEntity>) classEntity);
	}
	
	public Return sendEmail(){
		EmailManager email = new EmailManager("SimpleEmail");
		return email.sendActivationEmail("fernando.slopes.21@gmail.com");
	}
}
